package  
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	/**
	 * ...
	 * @author 
	 */
	public class Main1 extends MovieClip 
	{
		private static const _ROW_		:int = 6;
		private static const _COLUMN_	:int = 10;
		
		private static const _SPACE		:int = 5;
		
		private static const _NUM_OF_SAMPLE	:int = 15;
		
		private var arrValue	:Array;
		private var arrItem		:Array;
		
		private var matrix		:Array;
		
		private var mcItem1		:MovieClip;
		private var mcItem2		:MovieClip;
		
		//private var arrPoint	:Array;
		
		public function Main1() 
		{
			initGame();
		}
		
		private function initGame():void 
		{
			arrValue = [];
			arrItem = [];
			
			//arrPoint = [];
			
			mcItem1 = null;
			mcItem2 = null;
			
			var i:int;
			var j:int;
			
			// init matrix
			matrix = new Array(_ROW_ + 2);
			var arrChild:Array;
			
			for (i = 0; i < matrix.length; i++)
			{
				arrChild = new Array(_COLUMN_ + 2);
				
				for (j = 0; j < arrChild.length; j++)
				{
					if ( (i == 0) || (i == matrix.length - 1) || (j == 0) || (j == arrChild.length - 1 ) )
					{
						arrChild[j] = 0;
					} else
					{
						arrChild[j] = 1;
					}
				}
				
				matrix[i] = arrChild;
			}
			
			// init value array
			for (i = 0; i < _ROW_ * _COLUMN_; i++)
			{
				arrValue[i] = 0;
			}
			
			// set value of array & matrix
			var arrPos:Array = [];
			
			for (i = 0; i < arrValue.length; i++)
			{
				arrPos[i] = i;
			}
			
			var pos:int = 0;
			var index:int = 0;
			
			while (arrPos.length > 0)
			{
				for (i = 0; i < _NUM_OF_SAMPLE; i++)
				{
					if (arrPos.length == 0)
					{
						return;
					}
					
					pos = Math.floor(Math.random() * arrPos.length);
					arrValue[arrPos[pos]] = i + 1;
					arrPos.splice(pos, 1);
				}
			}
			
			var col:int;
			var row:int;
			
			for (i = 0; i < arrValue.length; i++)
			{
				row = Math.floor(i / _COLUMN_);
				col = i % _COLUMN_;
				
				matrix[row + 1][col + 1] = arrValue[i];
			}
			
			// init Item array
			var mcItem:MovieClip;
			
			for (i = 0; i < _ROW_ * _COLUMN_; i++)
			{
				mcItem = new ItemFC();
				mcItem.value = parseInt(arrValue[i]);
				
				mcItem.col = i % _COLUMN_ + 1;
				mcItem.row = Math.floor(i / _COLUMN_) + 1;
				
				mcItem.txtLabel.text = arrValue[i];
				
				arrItem.push(mcItem);
				
				mcContainer.addChild(mcItem);
				
				mcItem.x = (mcItem.width + _SPACE) * (i % _COLUMN_);
				mcItem.y = (mcItem.height + _SPACE) * Math.floor(i / _COLUMN_);
				
				mcItem.addEventListener(MouseEvent.CLICK, onClickCard);
			}
			
			mcContainer.x = stage.stageWidth / 2 - mcContainer.width / 2;
			mcContainer.y = stage.stageHeight / 2 - mcContainer.height / 2;
		}
		
		private function onClickCard(e:MouseEvent):void 
		{
			var item:MovieClip = e.currentTarget as MovieClip;
			
			if (mcItem1 == null)
			{
				while (mcPath.numChildren > 0)
				{
					mcPath.removeChildAt(0);
				}
				
				mcItem1 = item;
				mcItem1.gotoAndStop(2);
			} else
			{
				mcItem2 = item;
				
				if (mcItem1 != mcItem2)
				{
					if (mcItem1.value == mcItem2.value)
					{
						if (checkPosition(mcItem1.row, mcItem1.col, mcItem2.row, mcItem2.col))
						{
							mcContainer.removeChild(mcItem1);
							mcContainer.removeChild(mcItem2);
							
							matrix[mcItem1.row][mcItem1.col] = 0;
							matrix[mcItem2.row][mcItem2.col] = 0;
							
							traceMatrix();
						}
					} else {
						// unselect
					}
				}
				
				mcItem1.gotoAndStop(1);
				mcItem2.gotoAndStop(1);
				
				mcItem1 = null;
				mcItem2 = null;
				
				
			}
		}
		
		private function isFillAround(row:int, col:int):Boolean 
		{
			if (matrix[row][col - 1] == 0)
			{
				return false;
			}
			if (matrix[row][col + 1] == 0)
			{
				return false;
			}
			
			if (matrix[row - 1][col] == 0)
			{
				return false;
			}
			if (matrix[row + 1][col] == 0)
			{
				return false;
			}
			
			return true;
		}
		
		private function checkPosition(row1:int, col1:int, row2:int, col2:int):Boolean 
		{
			var result:Boolean = false;
			
			var numRow	:int = Math.abs(row1 - row2);
			var numCol	:int = Math.abs(col1 - col2);
			
			var i:int = 0;
			var j:int = 0;
			
			var arrPoint:Array = [];
			
			if ( ( (numRow == 1) && (numCol == 0) ) || ( (numRow == 0) && (numCol == 1) ) )
			{
				arrPoint[0] = new Point(col1 * 65, row1 * 85);
				arrPoint[1] = new Point(col2 * 65, row2 * 85);
				
				drawPath(arrPoint);
				
				return true;
			}
			
			if (isFillAround(mcItem1.row, mcItem1.col) || isFillAround(mcItem2.row, mcItem2.col))
			{
				return false;
			}
			
			var min:int;
			var max:int;
			if (numRow == 0)
			{
				min = Math.min(col1, col2);
				max = Math.max(col1, col2);
				if (checkRow(row1, min + 1, max - 1))
				{
					arrPoint[0] = new Point(col1 * 65, row1 * 85);
					arrPoint[1] = new Point(col2 * 65, row2 * 85);
					
					drawPath(arrPoint);
				
					return true;
				}
			}
			
			if (numCol == 0)
			{
				min = Math.min(row1, row2);
				max = Math.max(row1, row2);
				if (checkCol(col1, min + 1, max - 1))
				{
					arrPoint[0] = new Point(col1 * 65, row1 * 85);
					arrPoint[1] = new Point(col2 * 65, row2 * 85);
					
					drawPath(arrPoint);
				
					return true;
				}
			}
			
			if (checkHorizon(row1, col1, row2, col2))
			{
				return true;
			} else
			{
				return checkVertical(row1, col1, row2, col2);
			}
			
			return false;
		}
		
		private function checkHorizon(row1:int, col1:int, row2:int, col2:int):Boolean
		{
			var checkv1:Boolean;
			var checkh:Boolean;
			var checkv2:Boolean;
			
			var arrPoint	:Array = [];
			
			var i:int;
			var j:int;
			
			// col1           col2
			//  -  -  -  -  -  -
			//  -  -  -  -  -  1   ==> row2
			//  -  -  -  -  -  0
			//  0  0  0  0  0  0
			//  0  -  -  -  -  -
			//  1  -  -  -  -  -   ==> row1
			//  -  -  -  -  -  -
			
			// col1           col2
			//  -  -  -  -  -  -
			//  -  -  -  -  -  1   ==> row2
			//  -  -  -  -  -  0
			//  -  -  -  -  -  0
			//  1  -  -  -  -  0  ==> row1
			//  0  -  -  -  -  0  
			//  0  0  0  0  0  0
			
			var min:int;
			var max:int;
			for (i = 0; i < matrix.length; i ++) 
			{
				checkh = checkRow(i, col1, col2);
				
				if (checkh)
				{
					if (row1 == i)
					{
						checkv1 = true;
					} else if (row1 < i)
					{
						min = row1 + 1;
						max = i;
						checkv1 = checkCol(col1, min, max);
					} else
					{
						min = i;
						max = row1 - 1;
						checkv1 = checkCol(col1, min, max);
					}
					
					if (row2 == i)
					{
						checkv2 = true;
					} else if (row2 < i)
					{
						min = row2 + 1;
						max = i;
						checkv2 = checkCol(col2, min, max);
					} else
					{
						min = i;
						max = row2 - 1;
						checkv2 = checkCol(col2, min, max);
					}
					
					//checkv1 = checkCol(col1, row1, row2);
					//checkv2 = checkCol(col2, row1, row2);
					
					if (checkv1 && checkv2)
					{
						arrPoint[0] = new Point(col1 * 65, row1 * 85);
						arrPoint[1] = new Point(col1 * 65, i * 85);
						arrPoint[2] = new Point(col2 * 65, i * 85);
						arrPoint[3] = new Point(col2 * 65, row2 * 85);
						
						drawPath(arrPoint);
						
						return true;
					}
				}
			}
			
			return false;
		}
		
		private function checkVertical(row1:int, col1:int, row2:int, col2:int):Boolean
		{
			var checkh1:Boolean;
			var checkv:Boolean;
			var checkh2:Boolean;
			
			var arrPoint	:Array = [];
			
			var i:int;
			var j:int;
			
			//    col1        col2
			//  -  -  -  -  -  -
			//  0  0  0  0  0  1   ==> row2
			//  0  -  -  -  -  -
			//  0  -  -  -  -  -
			//  0  1  -  -  -  -   ==> row1
			//  -  -  -  -  -  -
			
			// col1           col2
			//  -  -  -  -  -  -
			//  -  -  0  0  0  1   ==> row2
			//  -  -  0  -  -  -
			//  -  -  0  -  -  -
			//  1  0  0  -  -  -   ==> row1
			//  -  -  -  -  -  -
			var min:int;
			var max:int;
			for (j = 0; j < matrix[0].length; j ++) 
			{
				checkv = checkCol(j, row1, row2);
				
				if (checkv)
				{
					if (col1 == j)
					{
						checkh1 = true;
					} else if (col1 < j)
					{
						min = col1 + 1;
						max = j;
						checkh1 = checkRow(row1, min, max);
					} else
					{
						min = j;
						max = col1 - 1;
						checkh1 = checkRow(row1, min, max);
					}
					
					if (col2 == j)
					{
						checkh2 = true;
					} else if (col2 < j)
					{
						min = col2 + 1;
						max = j;
						checkh2 = checkRow(row2, min, max);
					} else
					{
						min = j;
						max = col2 - 1;
						checkh2 = checkRow(row2, min, max);
					}
					
					//checkh1 = checkRow(row1, col1, col2);
					//checkh2 = checkRow(row2, col1, col2);
					
					if (checkh1 && checkh2) {
						
						arrPoint[0] = new Point(col1 * 65, row1 * 85);
						arrPoint[1] = new Point(j * 65, row1 * 85);
						arrPoint[2] = new Point(j * 65, row2 * 85);
						arrPoint[3] = new Point(col2 * 65, row2 * 85);
						
						drawPath(arrPoint);
						
						return true;
					}
				}
			}
			
			return false;
		}
		
		private function checkRow(row:int, start:int, end:int):Boolean { 
			
			//  -  -  -  -  -  -
			//  -  -  -  -  -  -
			//  1  0  0  0  0  1 ==> row
			//  -  -  -  -  -  -
			//  -  -  -  -  -  -
			// start          end
			
			var min:int = Math.min(start, end);
			var max:int = Math.max(start, end);
			
			for (var j:int = min; j <= max; j++) {
				
				if ( ((row != mcItem1.row) || (j != mcItem1.col)) && ((row != mcItem2.row) || (j != mcItem2.col)) )
				{
					if (matrix[row][j] != 0) {
						return false;
					}
				}
			}
			
			return true;			
		}
		
		private function checkCol(col:int, start:int, end:int):Boolean {			
			//       col
			//  -  -  1  -  -  - ==> start
			//  -  -  0  -  -  -
			//  -  -  0  -  -  - 
			//  -  -  0  -  -  -
			//  -  -  1  -  -  - ==> end
			
			var min:int = Math.min(start, end);
			var max:int = Math.max(start, end);
			
			for (var i:int = min; i <= max; i ++) {
				if ( ((col != mcItem1.col) || (i != mcItem1.row)) && ((col != mcItem2.col) || (i != mcItem2.row)) )
				{
					if (matrix[i][col] != 0) {
						return false;
					}
				}
			}
			
			return true;
		}
		
		private function drawPath(arrPoint:Array):void 
		{
			var spr:Sprite = new Sprite();
			
			spr.graphics.lineStyle(3, 0xFF0000, 1);
			spr.graphics.moveTo(arrPoint[0].x, arrPoint[0].y);
			
			for (var i = 1; i < arrPoint.length; i++)
			{
				spr.graphics.lineTo(arrPoint[i].x, arrPoint[i].y);
			}
			
			mcPath.addChild(spr);
			
			mcPath.x = mcContainer.x - 30;
			mcPath.y = mcContainer.y - 40;
		}
		
		private function traceMatrix():void 
		{
			for (var i = 0; i < matrix.length; i++)
			{
				trace(matrix[i]);
			}
			
			trace("---------------------------");
		}
	}

}
